package org.dyndns.opendemogroup.optimizer.operations;

import static org.junit.Assert.assertEquals;

import java.util.Random;

import org.dyndns.opendemogroup.optimizer.ArrayUtil;
import org.dyndns.opendemogroup.optimizer.IOperation;
import org.dyndns.opendemogroup.optimizer.IOptimizationProblem;
import org.dyndns.opendemogroup.optimizer.Member;

/**
 * Helper class to easily test IOperation implementations.
 */
public abstract class OperationTestBase
{
	private IOperation implementation;

	public OperationTestBase ( IOperation implementation )
	{
		this.implementation = implementation;
	}

	protected void checkPerform ( double[] one, double[] two,
			Random randomSource, IOptimizationProblem problem,
			double[] expectedChildOne, double[] expectedChildTwo )
	{
		// { sanity checks
		int length = one.length;
		assertEquals ( length, two.length );
		assertEquals ( length, expectedChildOne.length );
		assertEquals ( length, expectedChildTwo.length );
		// }

		// { set-up
		Member parentOne = new Member ( length );
		ArrayUtil.copy ( one, parentOne.genome, 0, length - 1 );
		Member parentTwo = new Member ( length );
		ArrayUtil.copy ( two, parentTwo.genome, 0, length - 1 );

		Member actualChildOne = new Member ( length );
		Member actualChildTwo = new Member ( length );
		// }

		implementation.perform ( randomSource, problem, parentOne, parentTwo,
			actualChildOne, actualChildTwo );

		// { validation
		checkChild ( actualChildOne, expectedChildOne );
		checkChild ( actualChildTwo, expectedChildTwo );
		// }
	}

	static void checkChild ( Member actualChild, double[] expectedChild )
	{
		final int memberSize = actualChild.getMemberSize ( );
		for ( int i = 0; i < memberSize; i++ )
		{
			String message =
				"Child: '" + actualChild.toString ( )
						+ "' is different at index [" + i + "].";
			assertEquals ( message, expectedChild[i], actualChild.genome[i] );
		}
	}
}
